Baklava

What is a sprite?

Sprites are graphical objects visible on the computer screen. Most sprites are also moving objects. Sprites are useful in the implementation of active imagemaps, puzzles, simulations, and games, among other possibilities. Sprites are aware of collisions with other sprites, as well as interactions with the mouse, the keyboard, and the edges of the playfield. Sprites always reside in playfields, which must be constructed first.

Other capabilities of sprites

Baklava sprites can be told what direction to move in and how fast to travel (in pixels per second), without further intervention from the programmer, until something "interesting" such as a collision takes place.

In addition, each sprite knows what "level" it is on. Sprites at higher levels are drawn on top. This allows "foreground" sprites to move across "background" sprites. It is also possible to specify that certain sprites never collide with others.

If the setImage method is used to assign an image that was loaded from a transparent GIF, then baklava will take this into account in determining collisions. This allows non-rectangular sprites to interact gracefully.

Extending Sprites: Yes, You Will Need To

To do truly interesting things with sprites, you will need to "subclass" them. This allows you to write your own class that has all of the built-in behavior of a sprite, plus the additional "smarts" necessary for your own application.

Receiving Events: Pick Up the Courtesy Phone...

Methods such as collisionWith, which do nothing in the "raw" Sprite class, are invoked by the playfield to let you know when one sprite collides with another sprite or with the edges of the playfield. You can replace these methods with useful versions in your subclass of Sprite.

Also, The very important timer method is invoked when a timer set by a call to setTimer or setTimerAll expires. Replace this method to carry out particular actions at particular times, or when notified by another sprite.

Other events that are reported to sprites are normally handled well by the built-in sprite code, but you can add additional behavior. Methods such as onStep and onGoodbye can optionally be replaced to move in more complex ways, or to carry out extra steps when a sprite is removed from a playfield.

About Sprites and Threads...

Implementing a separate thread for each sprite is not recommended. Instead, subclass the Sprite class to respond to various events, and use the setTimer method to carry out particular actions at particular times. Baklava takes great care to deliver timers in the correct order and to synchronize the delivery of timers and events in a safe and reliable manner.

Example: Shy Sprites

This applet contains a group of sprites which are uncomfortable with each other, and with you, for that matter. When they come in contact with one another or the mouse, they change direction and run away quickly. This is done by subclassing Sprite to add new versions of the collisionWith and mouseEnter methods.
import baklava.*;

// A private class implementing the shy sprites.
class Shy extends Sprite {

	// A timer ID we'll use later. "final" so java
	// will know it's just a constant and not
	// reserve any real space for it.
	final int timerSlowDown = 0;

	public Shy(Playfield p, Image image)
	{
		// Call the Sprite constructor. This is required.
		super(p);
		// Now set the image.
		setImage(image);
		// Pick a random location safely inside the playfield.
		// Math.random() returns a value between 0 and 1.
		int x = (int) (Math.random() * (p.getWidth() - getWidth()));
		int y = (int) (Math.random() * (p.getHeight() - getHeight()));
		// Set the location.
		setX(x);
		setY(y);
		// Set a direction.
		setDirection((int) (Math.random() * 360));
		// Set a speed.
		setSpeed(30);
		// Just bounce at the edges of the playfield.
		setEdgeHandling(edgeBounce);
	}	
	void collisionWith(Sprite s)
	{
		// We collided with something. Run awaaay!

		// Find the direction to the thing we collided with.

		int direction = getPlayfield().angleOfVector(
			getX(), getY(), s.getX(), s.getY());

		// Now go the other way...	
		direction += 180;
		setDirection(direction);	

		// And speed up
		setSpeed(60);

		// Set a timer to slow down after 2 seconds.
		setTimer(2000, timerSlowDown);
	}
	void mouseEnter(Event evt, int x, int y)
	{
		// The mouse entered the sprite. Run away.
		s